package cn.es.util;

import ch.qos.logback.core.net.SyslogOutputStream;
import cn.es.pojo.Content;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * elasticSearch工具类
 */
public class EsUtil {



    /**
     * 创建索引 判断索引是否存在，如果存在则返回true，如果不存在，则创建
     * 创建成功返回true
     * @return
     * @throws IOException
     */
    public static boolean createIndex(RestHighLevelClient client,String index) throws IOException {
        //1、获取查询索引（库） 的请求
        GetIndexRequest request= new GetIndexRequest(index);
        //2、判断该索引是否存在
        boolean flag_exist= client.indices().exists(request,RequestOptions.DEFAULT);
        if (flag_exist){
            //如果存在该索引，则返回true
            return true;
        }
        //如果不存在，该索引，则创建该索引
        //3、创建新建索引（库） 的请求
        CreateIndexRequest createIndexRequest= new CreateIndexRequest(index);
        //4、执行请求，获得响应
        CreateIndexResponse createIndexResponse= client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        return  createIndexResponse.isAcknowledged();
    }

    /**
     * 从京东网页获取数据，批量插入elasticSearch数据
     * @param key
     * @param index
     * @return
     * @throws IOException
     */
    public static boolean insertListEs(RestHighLevelClient client,String key,String index) throws IOException {
        //1、创建大批量数据插入请求
        BulkRequest request = new BulkRequest();
        //2、设置超时时间
        request.timeout("10s");
        //3、从京东网页中抓取数据，封装为实体类集合
        List<Content> contents = HtmlParseUtil.getList(key);

        //4、判断是否存在该索引
        if (createIndex(client,index)) {
//            没有就创建，有就执行使用
            //5、此时存在该索引，往该索引插入数据
            for (Content content : contents) {

                request.add(
                        new IndexRequest(index)
//                                .id(String.valueOf(content.getId())) # 重复的id会覆盖之前的数据 因为不是从数据库中查询，没有唯一的主键id，所以暂时不指定id
                                .source(JSON.toJSONString(content), XContentType.JSON));
            }
            BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
            return !response.hasFailures();
        }
        return false;
    }
    public static List<Map<String,Object>> searchEs(RestHighLevelClient client,String index,String key,int pageNum,int pageSize) throws IOException {
        List<Map<String,Object>> list=new ArrayList<>();
        //1、条件搜索 参数 索引
        SearchRequest searchRequest=new SearchRequest(index);
        //2、构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //3、分页
        int begin=(pageNum-1)*pageSize;
        searchSourceBuilder.from(begin);
        searchSourceBuilder.size(pageSize);

        //4、查询条件 全文搜索
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", key);
        //5、注入执行查询条件
        searchSourceBuilder.query(matchQueryBuilder);
        //6、设置查询超时时间
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        //7、执行查询 返回结果
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(response);
        for (SearchHit hit : response.getHits().getHits()) {
            //遍历查询结果
            System.out.println(hit.getSourceAsMap());
            Map<String, Object> map = hit.getSourceAsMap();
            System.out.println(map);
            list.add(map);
        }
        //返回结果
        return list;
    }
    public static List<Map<String,Object>> searchEsHighlight(RestHighLevelClient client,String index,String key,int pageNum,int pageSize) throws IOException {
        List<Map<String,Object>> list=new ArrayList<>();
        //1、条件搜索 参数 索引
        SearchRequest searchRequest=new SearchRequest(index);
        //2、构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //3、分页
        int begin=(pageNum-1)*pageSize;
        searchSourceBuilder.from(begin);
        searchSourceBuilder.size(pageSize);

        //4、查询条件 全文搜索
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", key);

        //高亮
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("title");
        //前缀 后缀
        highlightBuilder.preTags("<p class='light' style='color:red'>");
        highlightBuilder.postTags("</p>");
        searchSourceBuilder.highlighter(highlightBuilder);
        highlightBuilder.requireFieldMatch(false);//一个文档只显示一个高亮
        //5、注入执行查询条件
        searchSourceBuilder.query(matchQueryBuilder);
        //6、设置查询超时时间
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        //7、执行查询 返回结果
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        for (SearchHit hit : response.getHits().getHits()) {
            //遍历查询结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            HighlightField title = highlightFields.get("title");
            Map<String, Object> map = hit.getSourceAsMap();//原来的结果

            //解析高亮字段 将之前没有高亮的字段替换为现在高亮的字段即可
            if (title!=null){
                Text[] fragments = title.fragments();
                String newTitle="";
                for (Text fragment : fragments) {
                    newTitle+=fragment;
                }
                hit.getSourceAsMap().put("title",newTitle);
            }
            list.add(map);
        }
        //返回结果
        return list;
    }



}
